home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1995-12-31 | 64.1 KB | 1,699 lines | [ TEXT/R*ch]
C.S.M.P. Digest Fri, 02 Jun 95 Volume 3 : Issue 99 Today's Topics: Async MacTCP PowerPC woes... C++ Working Paper Error Checking How to program network licence Keyboard events from a background application MIDI Books & other stuff New PowerPC Assembly Language Book Printing Styled TextEdit QuickDraw 3D Info QuickTake API? WakeUpProcess at Interrupt Time The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier (pottier@clipper.ens.fr). The digest is a collection of article threads from the internet newsgroups comp.sys.mac.programmer.help, csmp.tools and csmp.misc. It is designed for people who read news semi-regularly and want an archive of the discussions. If you don't know what a newsgroup is, you probably don't have access to it. Ask your systems administrator(s) for details. If you don't have access to news, you may still be able to post messages to the group by using a mail server like anon.penet.fi (mail help@anon.penet.fi for more information). Each issue of the digest contains one or more sets of articles (called threads), with each set corresponding to a 'discussion' of a particular subject. The articles are not edited; all articles included in this digest are in their original posted form (as received by our news server at nef.ens.fr). Article threads are not added to the digest until the last article added to the thread is at least two weeks old (this is to ensure that the thread is dead before adding it to the digest). Article threads that consist of only one message are generally not included in the digest. The digest is officially distributed by two means, by email and ftp. If you want to receive the digest by mail, send email to listserv@ens.fr with no subject and one of the following commands as body: help Sends you a summary of commands subscribe csmp-digest Your Name Adds you to the mailing list signoff csmp-digest Removes you from the list Once you have subscribed, you will automatically receive each new issue as it is created. The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest. Questions related to the ftp site should be directed to scott.silver@dartmouth.edu. ------------------------------------------------------- >From wem53067@uxa.cso.uiuc.edu (TheBard) Subject: Async MacTCP PowerPC woes... Date: Sun, 07 May 1995 06:40:28 -0600 Organization: Bard 'O Matic Software Ok, I'm having quite a frustrating problem. It seems that my asyc calls are randomly causing my Powermac to crash. It hard to tell exactly whats going on, but I know the crash is not hapening untill the exact moment an async call is made. Here is my code: OSErr LowTCPWaitForConnection(StreamPtr streamPtr,byte timeout,ip_addr *remoteHost, tcp_port *remotePort,ip_addr *localHost,tcp_port *localPort, Boolean async,TCPiopb **returnBlock) { OSErr err; TCPiopb *pBlock; TCPIOCompletionUPP myProc; myProc = NewTCPIOCompletionProc((ProcPtr)NotifyConnected); if ((err = NewBlock(&pBlock)) != noErr) return err; pBlock->csCode = TCPPassiveOpen; //pBlock->ioResult = 1; pBlock->ioCompletion = myProc; pBlock->tcpStream = streamPtr; pBlock->csParam.open.ulpTimeoutValue = timeout; pBlock->csParam.open.ulpTimeoutAction = 0; pBlock->csParam.open.validityFlags = 0xC0; pBlock->csParam.open.commandTimeoutValue = timeout; pBlock->csParam.open.remoteHost = 0; pBlock->csParam.open.remotePort = 0; pBlock->csParam.open.localPort = *localPort; pBlock->csParam.open.tosFlags = 0; pBlock->csParam.open.precedence = 0; pBlock->csParam.open.dontFrag = 0; pBlock->csParam.open.timeToLive = 0; pBlock->csParam.open.security = 0; pBlock->csParam.open.optionCnt = 0; PBControl((ParmBlkPtr)pBlock,true); return noErr; } The boolean asynch is true, and all prarametrs are valid. and the asych routine is: void NotifyConnected(TCPiopb myPB) { gTest = TRUE; } All the async routine is doing is flipping a global Boolean. Now, I guess my first question has to do with the UniversalProcPtr's. After looking through the Universal Headers, I'm assuming the correct call is NewTCPIOCompletionProc. If not, what is it? The reason I'm assuming it is that sometimes when an incoming conntion trigers my async call, everything works fine. Other times, I get freezes and bombs such as "Illegal Instruction", ect. So, I think whats hapening is the mode manager is getting confused or something. I'm not sure at all here. Can someone help me out? Wayde -- ======================================================================== --=The Bard=-- "Just remember, no matter where you go, there you are!" - ---------------------------------------------------------------------- PGP Public Key available upon request. +++++++++++++++++++++++++++ >From hawkfish@halcyon.com (Richard Wesley) Date: 7 May 1995 21:00:08 GMT Organization: Punch Deck Consulting In article <wem53067-0705950640280001@antwerp-2.slip.uiuc.edu> wem53067@uxa.cso.uiuc.edu (TheBard) writes: > pBlock->csParam.open.optionCnt = 0; > PBControl((ParmBlkPtr)pBlock,true); > > return noErr; > } > Always check the error return for Device manager calls (but ignore them with File Manager calls) Probably not your problem, but good practice. > The boolean asynch is true, and all prarametrs are valid. > > and the asych routine is: > > void NotifyConnected(TCPiopb myPB) > { > gTest = TRUE; > } > > All the async routine is doing is flipping a global Boolean. > This should be (TCPiopb *myPB), which might be screwing up your stack in the Mixed Mode switch. Also, I suggest using C++ and storing an object pointer in the pb.userDataPointer - saves globals and makes your code more reusable once you get this fixed. Declare the callback as a private static member. > Now, I guess my first question has to do with the UniversalProcPtr's. > After looking through the Universal Headers, I'm assuming the correct call > is NewTCPIOCompletionProc. If not, what is it? The reason I'm assuming it > is that sometimes when an incoming conntion trigers my async call, > everything works fine. Other times, I get freezes and bombs such as > "Illegal Instruction", ect. So, I think whats hapening is the mode manager > is getting confused or something. I'm not sure at all here. Can someone > help me out? I would guess that this is a timeout problem - sometimes the connection comes in and sometimes it doesn't. You are not checking error values in your callback routine so you always assume that the connection succeeds. You may then be using an invalid data structure for the connection. - rmgw - ------------------------------------------------------------------------------ Richard Wesley hawkfish@halcyon.com | "Oh boy! Did you forget the plot Punch Deck Consulting pnchdeck@aol.com | _again_?" Macintosh Software Development | - Rocket J. Squirrel - ------------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From hawkfish@halcyon.com (Richard Wesley) Date: 9 May 1995 18:07:36 GMT Organization: Punch Deck Consulting In article <wem53067-0705952026120001@berlin-2.slip.uiuc.edu> wem53067@uxa.cso.uiuc.edu (TheBard) writes: > Welp, I don't know if its a timeout problem. if it times out, the async > call should still be made. Here is a question though - If I accidently > declared the buffer for the stream to be X, and passed the length as x*2, You could easily overwrite random bits of memory, leading to the kinds of problems you are seeing. NEVER do this! > would this mess the asyc up? I'm positive it would on the reads and writes > as soon as I started bushing past the end of the buffer.. but how about > Asynch? Makes no difference. - rmgw - ------------------------------------------------------------------------------ Richard Wesley hawkfish@halcyon.com | "Oh boy! Did you forget the plot Punch Deck Consulting pnchdeck@aol.com | _again_?" Macintosh Software Development | - Rocket J. Squirrel - ------------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From ari@shore.net (Ari Halberstadt) Date: Thu, 11 May 1995 01:37:57 -0400 Organization: North Shore Access/Eco Software, Inc; (info@shore.net) In article <wem53067-0705950640280001@antwerp-2.slip.uiuc.edu>, wem53067@uxa.cso.uiuc.edu (TheBard) wrote: > Ok, I'm having quite a frustrating problem. It seems that my asyc calls > are randomly causing my Powermac to crash. It hard to tell exactly whats > going on, but I know the crash is not hapening untill the exact moment an > async call is made. I don't know exactly what's causing the crash. Last month, I was trying to do async file manager completion routines on my PPC and the thing crashed left and right (it was crashing left and right anyway, due to extension and driver conflicts, but that's another matter). Not to mention the really weird stuff I was doing (for no good reason, I might add :-) Anyway, a couple of tricks I've found helpful in debugging this sort of muck. 1. Always clear the *entire* param block. It's not strictly necessary, but it can make debugging a lot easier if you forget to clear something that should be cleared. Later, when it's all debugged, you can remove the extra intialization. Before filling in the PB fields, just do: memset(pb, 0, sizeof(TypeOfPB)); I do this so often, and can never remember if the zero goes before or after the sizeof (I had to check in Think Reference), that I have another function void memclr(void *p, size_t n); This is good, since on the PPC I can hack a really fast zero assembler stub, not that I've had to do that yet. Also, I don't get that (discarded) return value, of which I always feel guilty for not explicitely casting memset to void. Am I a geek, or what? 2. Always assume every stupid little tiny trivial thing you do will fail. This seems to always be true when I program. It will especially fail if you call the TB, which means checking every single tiny error return (as mentioned in a prior post) and complaining loudly or *correctly* recovering, your choice. 3. Don't use a completion routine. Use the asnc call, but just poll for completion. You can do that in FM calls, so--not having my TCP reference handy--I assume you can do it in TCP calls. This at least will tell you whether it's the completion routine or something completely unrelated. In my experience, 90% of the time it's the completion routine, and 70% of the time it's something completely unrelated. The completely unrelated events are usually derived from the current phase of the moon divided by the rate at which the crickets in Maine are chirping. 4. You've got a mondo memory leak, you're always allocating a new completion proc and a new parameter block. Here's my trick for OS callback routines: static pascal t0 FavoriteCallback(t1 p1, t2 p2, ..., tN pN) { ... } FavoriteUPP uppFavoriteCallback(void) { static FavoriteUPP upp = NULL; if (! upp) { upp = NewFavoriteUPP(FavoriteCallback); FailNIL(upp); } return(upp); } Lovely, ain't it? Now type this idiom 100 times. Don't you wish you had generic functions? Anyway, this is great, since you won't go passing a non-UPP function around, the UPP is allocated only once (and never again!), etc. I think this would even work in C++ land, since the static variable would get initialized when the thread of control passed through the function (or is it the compilation unit?) > Here is my code: > > OSErr LowTCPWaitForConnection(StreamPtr streamPtr,byte timeout,ip_addr > *remoteHost, > tcp_port *remotePort,ip_addr *localHost,tcp_port *localPort, > Boolean async,TCPiopb **returnBlock) > { > OSErr err; > TCPiopb *pBlock; > TCPIOCompletionUPP myProc; > > myProc = NewTCPIOCompletionProc((ProcPtr)NotifyConnected); > > if ((err = NewBlock(&pBlock)) != noErr) > return err; > and the asych routine is: > > void NotifyConnected(TCPiopb myPB) Pascal. Always make callbacks type pascal. Good to make them static functions as well. Besides the comment in a prior post about not using globals, don't forget you're going to compile this for 68K. So remember to set and restore A5 (though you were probably just simplifying the routine for debugging). > everything works fine. Other times, I get freezes and bombs such as > "Illegal Instruction", ect. So, I think whats hapening is the mode manager > is getting confused or something. I'm not sure at all here. Can someone > help me out? But hey, you have a PowerMac! It doesn't say "Illegal F-line instruction" anymore. What could be cooler? :-) +++++++++++++++++++++++++++ >From scouten@metrowerks.com (Eric Scouten) Date: Fri, 12 May 1995 00:38:51 -0700 Organization: metrowerks, inc. In article <ari-1105950137570001@198.115.179.207>, ari@shore.net (Ari Halberstadt) wrote: [TCP debugging suggestions] > 1. Always clear the *entire* param block > 2. Always assume every stupid little tiny trivial thing you do will fail. These are good suggestions. > 3. Don't use a completion routine. Use the asnc call, but just poll for > completion. Bad idea. This essentially makes your code synchronous, which is a rather different case. Furthermore, it will cause your application to exhibit incorrect behavior or even crash if you use this technique with DNR code segment calls. Here's why: The DNR code segment often stores intermediate results in the result parameter field before it decides what the story really is and calls your completion proc. These are often error codes like the name server is not responding, which can be very misleading to you. When working with DNR calls, you *really* have no choice but to write your code to be truly asynchronous. > 4. You've got a mondo memory leak, you're always allocating a new > completion proc and a new parameter block. Yup. -es __________________________________________________________________________ Eric Scouten Constructor Constructor scouten@metrowerks.com Metrowerks, Inc. OUT OF TOWN May 6-June 4: WWDC & vacation Furthermore, in my mad haste to switch CDs, I dragged the Inside Mac CD-ROM icon to the trash and when the Mac ejected it, the tray pushed a glass of grape juice off my desk and into my lap. Let that be a lesson to development tool vendors: all this would have been avoided with better documentation. -Miguel Cruz <mnc@netcom.com> --------------------------- >From kenp@nmrfam.wisc.edu (Ken Prehoda) Subject: C++ Working Paper Date: Tue, 16 May 1995 15:04:25 -0500 Organization: Univ of Wisc-Madison, Dept of Biochemistry I thought some of you may be interested to know it is no longer necessary to purchase the current version of the ISO working paper on C++. You can now read the current stab at a standard via this URL: ftp://research.att.com//dist/c++std/WP/ The document is in both postscript and acrobat formats. -- Ken Prehoda, kenp@nmrfam.wisc.edu --------------------------- >From mcconnel@math.washington.edu Subject: Error Checking Date: 9 May 1995 19:42:19 GMT Organization: University of Washington Department of Mathematics Hello out there... I'd like to know what the hard and fast rules are for Error Checking. Most of the Sample Code I've been looking at does precious little Checking, and even "real" Documentation says stuff like "You should, of course, include Error Checking routines, which we've left out ..."; some Books on beginning Programming don't make a big deal out of it, either (perhaps because the Sample Programs are designed to be fairly innocuous), so I've gotten no real formal training in this particular aspect of Programming. I realize that the basic rule is CHECK EVERYTHING, and I'm fine with that, but how do I go about checking everything (and should I truly expect my Code to wind up alternating Call/Check/Call/Check/Call/Check... all the way through)? Is there any kind of compilation of Error Checks out there, giving a quick reference (or even just general guidelines) for exactly how to Check various Toolbox Calls or whatnot (perhaps prioritizing things a bit, indicating things that one should *always* check immediately or often and things that one can check more casually); or do I just have to flip through the Inside Macintosh texts and look up how to check each Call? What say ye? Your help is greatly appreciated. Regards, Don Don McConnell mcconnel@math.washington.edu University of Washington Department of Mathematics +++++++++++++++++++++++++++ >From pottier@drakkar.ens.fr (Francois Pottier) Date: 10 May 1995 10:26:05 GMT Organization: Ecole Normale Superieure, Paris In article <3oogir$j1t@nntp5.u.washington.edu>, <mcconnel@math.washington.edu> wrote: >realize that the basic rule is CHECK EVERYTHING, and I'm fine with that, but >how do I go about checking everything (and should I truly expect my Code to >wind up alternating Call/Check/Call/Check/Call/Check... all the way through)? Yes. Checking everything is of utmost importance if you write software to be used by others. If you use C/Pascal your code will actually end up looking as Call/Check/etc. A better alternative is to use C++, which has exceptions. They can make the task a lot simpler by making most of the error checking transparent. (That's why I'm impatient to get my hands onto CW6...) -- Francois Pottier pottier@dmi.ens.fr - ---------------------------------------------------------------------------- Check my WWW page at http://acacia.ens.fr:8080/home/pottier/ ... +++++++++++++++++++++++++++ >From sandvik@apple.com (Kent Sandvik) Date: Thu, 11 May 1995 00:13:30 -0800 Organization: Apple Computer, Inc. Developer Technical Support In article <3oogir$j1t@nntp5.u.washington.edu>, mcconnel@math.washington.edu wrote: > Hello out there... > > I'd like to know what the hard and fast rules are for Error Checking. > > Most of the Sample Code I've been looking at does precious little Checking, > and even "real" Documentation says stuff like "You should, of course, > include Error Checking routines, which we've left out ..."; some Books on > beginning Programming don't make a big deal out of it, either (perhaps > because the Sample Programs are designed to be fairly innocuous), so I've > gotten no real formal training in this particular aspect of Programming. I > realize that the basic rule is CHECK EVERYTHING, and I'm fine with that, but > how do I go about checking everything (and should I truly expect my Code to > wind up alternating Call/Check/Call/Check/Call/Check... all the way through)? > Is there any kind of compilation of Error Checks out there, giving a quick > reference (or even just general guidelines) for exactly how to Check various > Toolbox Calls or whatnot (perhaps prioritizing things a bit, indicating things > that one should *always* check immediately or often and things that one can > check more casually); or do I just have to flip through the Inside Macintosh > texts and look up how to check each Call? Check out my QT samples for code for that has *too much error checking*, I guess too much is never too much. ftp://ftp.info.apple.com/dts/quicktime/dtsqtutils.May95.hqx Anyway, I test incoming parameters so they are valid, do MemErr() and similar calls after each trap called, test for error number with assertions, id absurdum. And some of that extensive testing could be disabled because the macros operate with flags. In general I don't mind testing like crasy with d-releases, and disable most of the extensive testing when shipping something. Cheers, Kent -- Kent Sandvik sandvik@apple.com Working with Multimedia stuff... Apple Developer Technical Support. Private activities on Internet. +++++++++++++++++++++++++++ >From dstone@alchemy.chem.utoronto.ca (David Stone) Date: Thu, 11 May 1995 13:03:58 GMT Organization: University of Toronto Chemistry In article <sandvik-1105950013300001@17.255.38.116>, sandvik@apple.com (Kent Sandvik) wrote: > > In article <3oogir$j1t@nntp5.u.washington.edu>, > mcconnel@math.washington.edu wrote: > > > Hello out there... > > > > I'd like to know what the hard and fast rules are for Error Checking. > > > > Most of the Sample Code I've been looking at does precious little Checking, > > and even "real" Documentation says stuff like "You should, of course, > > include Error Checking routines, which we've left out ...";> =====snip====== > Check out my QT samples for code for that has *too much error checking*, I > guess too much is never too much. > > ftp://ftp.info.apple.com/dts/quicktime/dtsqtutils.May95.hqx > > Anyway, I test incoming parameters so they are valid, do MemErr() and > similar calls after each trap called, test for error number with > assertions, id absurdum. And some of that extensive testing could be > disabled because the macros operate with flags. In general I don't mind > testing like crasy with d-releases, and disable most of the extensive > testing when shipping something. Similar stuff here, although I'm still hazy on assertions. Example, if a routine requires a copy of a handle passed to it DoSomething(Handle data) { if(data == 0L) return; } Even better is to return a completion code or error code so that the calling routine knows whether or not something happened - like the many Toolbox calls that return an OSErr which are often ignored. Good things to check are successful memory allocation and resource loading, since MemErr/ResErr will be set if there was a problem and the returned handle will by nil... myHandle = NewHandle(sizeof(MyData)); if(myHandle == 0L) return (errorCode); I'm sure there's much more you can do too, like range-checking variables etc. Dave Stone +++++++++++++++++++++++++++ >From Carl R. Osterwald <carl_osterwald@nrel.gov> Date: 11 May 1995 15:47:45 GMT Organization: National Renewable Energy Laboratory In article <osterD8Eooq.LzD@netcom.com> David Phillip Oster, oster@netcom.com writes: >Here is an "error ladder": > > if(noErr == errCode){ errCode = FSpOpenDF(fs, fsCurPerm, &ref); } > if(noErr == errCode){ errCode = GetEOF(ref, &len);} > if(noErr == errCode && len < 512){ errCode = eBadPict; } > if(noErr == errCode){ len -= 512; errCode = SetFPos(ref, fsFromStart, 512L); } > if(noErr == errCode){ ph = (PicHandle) NewHandle(len); errCode = MemError(); } This is all really very good, and I try to do things much like this, but what if something strange is happening in the middle of the ladder and you need to find out where in the ladder the problem is occuring? One solution is to have an integer incremented after each rung. This number can be put in the error report so that you can pin down the exact location. +++++++++++++++++++++++++++ >From sandvik@apple.com (Kent Sandvik) Date: Sun, 14 May 1995 18:56:52 -0800 Organization: Apple Computer, Inc. Developer Technical Support In article <3otbj1$1ak@nrel.nrel.gov>, Carl R. Osterwald <carl_osterwald@nrel.gov> wrote: > In article <osterD8Eooq.LzD@netcom.com> David Phillip Oster, > oster@netcom.com writes: > >Here is an "error ladder": > > > > if(noErr == errCode){ errCode = FSpOpenDF(fs, fsCurPerm, &ref); } > > if(noErr == errCode){ errCode = GetEOF(ref, &len);} > > if(noErr == errCode && len < 512){ errCode = eBadPict; } > > if(noErr == errCode){ len -= 512; errCode = SetFPos(ref, fsFromStart, 512L); } > > if(noErr == errCode){ ph = (PicHandle) NewHandle(len); errCode = MemError(); } > > This is all really very good, and I try to do things much like this, but > what if something strange is happening in the middle of the ladder and > you need to find out where in the ladder the problem is occuring? One > solution is to have an integer incremented after each rung. This > number can be put in the error report so that you can pin down the > exact location. That's why I assert every time I call a function concerning the OSErr being noErr. Ex: anErr = OpenMovieFile(theFSSpec, theRefNum, fsRdPerm); DebugAssert(anErr == noErr); The Macro used: #if DEBUG static char gDebugString[256]; #define DebugAssert(condition) \ if (condition) NULL; \ else \ { \ sprintf(gDebugString,"File: %s, Line: %d", __FILE__, __LINE__); \ DebugStr(c2pstr(gDebugString)); \ } #else #define DebugAssert(condition) NULL #endif Two things: 1. If DEBUG is not enabled, then the Asserts become NULL statements, and most decent compilers will optimize away this as well. 2. If I use MW debugger, if the assert triggers, then I usually drop into the MW debugger rather than MacsBug. In other words to the exact problem line. This has saved me so many minutes concerning development it's incredible (and a big hug to the MW people who implemented this nice feature for the MW debugger). --Kent -- Kent Sandvik sandvik@apple.com Working with Multimedia stuff... Apple Developer Technical Support. Private activities on Internet. +++++++++++++++++++++++++++ >From ari@shore.net (Ari Halberstadt) Date: Sun, 14 May 1995 00:17:04 -0400 Organization: North Shore Access/Eco Software, Inc; (info@shore.net) In article <3oq4bt$rif@nef.ens.fr>, pottier@drakkar.ens.fr (Francois Pottier) wrote: > In article <3oogir$j1t@nntp5.u.washington.edu>, > <mcconnel@math.washington.edu> wrote: > > >realize that the basic rule is CHECK EVERYTHING, and I'm fine with that, but > >how do I go about checking everything (and should I truly expect my Code to > >wind up alternating Call/Check/Call/Check/Call/Check... all the way through)? > > Yes. Checking everything is of utmost importance if you write software to > be used by others. > > If you use C/Pascal your code will actually end up looking as Call/Check/etc. > A better alternative is to use C++, which has exceptions. They can make the > task a lot simpler by making most of the error checking transparent. > > (That's why I'm impatient to get my hands onto CW6...) Exceptions are the best. They are available in Pascal, at least they were in 68K land with Apple's special thingy. It's pretty straightforward to add exceptions in quite portable C (well, I don't know if it really is portable since it relies on some specific behaviors of volatile and setjmp/longjmp, though my stuff is mac-only, and it does work and it is all ANSI C). There are some lovely gotchas with exceptions. Like trying to use them with threads, since you need to have a separate exception stack per thread, or else wave your program goodbye. And innocent looking code like: ... state = HGetState(h); HLock(h); MayRaiseException(); HUnlock(h); ... may (will) leave a locked block in your heap for the rest of eternity. And code like: OSErr MacOSCallBack(...) { ... MayRaisException() ... return(noErr); } could make MacOS angry at you. Better: OSErr MacOSCallBack(...) { TRY { ... MayRaiseException() ... } CATCH { err = error number; NOPROPAGATE; } ENDTRY; return(err); } Proper integration with the language helps, so C++ exceptions are a good thing, though I wish they'd propagate automatically. Anyway, exceptions make software easier to write, understand, and debug. They're invaluable. +++++++++++++++++++++++++++ >From dstone@alchemy.chem.utoronto.ca (David Stone) Date: Wed, 17 May 1995 13:03:31 GMT Organization: University of Toronto Chemistry In article <95051423394100973@flugor.si.sub.de>, Andreas Franz <root@flugor.si.sub.de> wrote: > =====snip===== > > > What i'm doing is something like an easy method: I'm dividing my program into > several logical pieces. If i receive an error within on of those routines, i > make sure that this routine returns with an error-code and does not change > anything. Because this routine has returned an error, the calling routine gets > this error-code and returns itself without changing the state entered when > beeing called. Doing so ensures that everything has been cleaned up when the > program reports the error. > > look at this example: > > void main() > { > OSErr err; > > err = CreateFile(); > if(!err) > { > err=AddSomeData(); > } > CloseFile(); > if(err) > { > DeleteFile(); > } > } The other advantage here is debugging - each routine can/will generate a stack frame, allowing you to see how far you've gone through your code. EG. to use with MacsBug, you would set compiler options to always generate stack frames and MacsBug names. Then if you find yourself in MacsBug a stack crawl will give you much more info., plus when you "ip" the code you'll have a much better idea where you are. Dave Stone --------------------------- >From hofstede@inter.NL.net (O.A. ter Hofstede) Subject: How to program network licence Date: Mon, 8 May 1995 19:40:28 GMT Organization: NLnet Hi there! I am looking for a method to prevent my application from running more than a fixed number of times at the same time within a network environment (ie. I want to be able to ditribute my program with a network licence for X users). First I thought about Process to Process Communication, shared lock-files, etc., but these methods easily break down (program linking turned off, read-only volumes, etc.) Does anyone know a (simple) reliable method I can use? Any ready-to-use code somewhere? Please send any replies to ter.hofstede@applelink.apple.com. Thanx! Oscar. -- - ---------------------------------------------------------------------------- Oscar ter Hofstede Email: hofstede@adgraphics.nl Phone: +31 5910 40900 Fax: +31 5910 43883 BBS: +31 5910 48529 - ---------------------------------------------------------------------------- +++++++++++++++++++++++++++ >From nick+@pitt.edu ( nick.c ) Date: Mon, 08 May 1995 16:31:53 -0400 Organization: The Pitt, Chemistry In article <D89ynG.7uG@inter.NL.net>, hofstede@inter.NL.net (O.A. ter Hofstede) wrote: >I am looking for a method to prevent my application from running more than >a fixed number of times at the same time within a network environment (ie. >I want to be able to ditribute my program with a network licence for X users). >First I thought about Process to Process Communication, shared lock-files, >etc., but these methods easily break down (program linking turned off, >read-only volumes, etc.) The method NOW Utilities, Timbuktu, ChemDraw, and others use is to register a ficticious device on the network with the name being single serial number of the license. Other attempts to register the same device/serial# give an error that the program acts on to deny the user use of the program. When the program quit's (or crashes :-) the fictious device falls off the network, and another user can use the license. You could do a similiar routine that tries to register a license number, but if it gets an error increments the license number, and tries again until it can find a unique license or until it increments more than the number of licenses you have it configured for. Any user can use the program so long as the maximum number of licenses aren't being used. The number of licenses and base license number could be distributed in the form of an encrypted "registration number" that the program prompts for at startup and stores in it's preferences file. That way you only have to distribute a single binary, and site licensees can trivially upgrade the number of their licenses by getting a new reg number from you and just deleting their preference files. Chapter 10 of _NIM: Networking_ may be a useful reference for this. Disclaimer: I've never written this kind of code. >Does anyone know a (simple) reliable method I can use? Any ready-to-use >code somewhere? I think "Incognito" with source is availabe on sumex and/or umich. It's source would be a valuable reference. >Please send any replies to ter.hofstede@applelink.apple.com. Done. ---------------------= Nicholas C. DeMello =-------------------- Internet: nick+@pitt.edu _/ _/ _/ _/_/_/ _/ _/ eWorld: nick _/_/ _/ _/ _/ _/ _/_/_/ CIS: 71232,766 _/ _/_/ _/ _/ _/ _/ http://www.pitt.edu/~nick/ _/ _/ _/ _/_/_/ _/ _/ >From hofstede@inter.NL.net (O.A. ter Hofstede) Subject: How to program network licence Date: Mon, 8 May 1995 19:37:59 GMT Organization: NLnet Hi there! I am looking for a method to prevent my application from running more than a fixed number of times at the same time within a network environment (ie. I want to be able to ditribute my program with a network licence for X users). First I thought about Process to Process Communication, shared lock-files, etc., but these methods easily break down (program linking turned off, read-only volumes, etc.) Does anyone know a (simple) reliable method I can use? Any ready-to-use code somewhere? Thanx! Oscar. -- - ---------------------------------------------------------------------------- Oscar ter Hofstede Email: hofstede@adgraphics.nl Phone: +31 5910 40900 Fax: +31 5910 43883 BBS: +31 5910 48529 - ---------------------------------------------------------------------------- +++++++++++++++++++++++++++ >From ray@xfe.dfrc.nasa.gov (Jeff Ray) Date: Tue, 9 May 1995 17:18:11 GMT Organization: NASA Dryden FRC In article <D89ynG.7uG@inter.NL.net>, hofstede@inter.NL.net (O.A. ter Hofstede) wrote: > I am looking for a method to prevent my application from running more than > a fixed number of times at the same time within a network environment (ie. > I want to be able to ditribute my program with a network licence for X users). > First I thought about Process to Process Communication, shared lock-files, > etc., but these methods easily break down (program linking turned off, > read-only volumes, etc.) > Does anyone know a (simple) reliable method I can use? Any ready-to-use > code somewhere? The usual method, as another posted said, is to use some kind of NBP scheme. Call Sassafras at (603) 643-3351. They market the "KeyServer" license metering system, and they wrote an NBP-based copy protection library for developers to use so that it would work properly with their system. (I guess they got tired of rewriting their software everytime someone cooked up a new copy protection scheme.) Contrary to what you might think, it does not require that either you or your users have a KeyServer installed. It just does the right thing if they do. Cheap (or it was, last time I checked) and tested, so you can concentrate on your apps functionallity. Their most recent advertising talks about a LSAPI (License Server API), which appears to be an emerging industry standard for handling this sort of thing. Disclaimer: After doing all this research, I, myself, wound up not using their library, because to date all my apps have been release without copy protection. -- Jeff Ray M/S 4840A Official Correspondence Only: NASA/CSC Internet: ray@xfe.dfrc.nasa.gov Dryden Flight Research Center P. O. Box 273 All Others: Edwards, CA 93523-5000 AOL: Jeff Ray (jeffray@aol.com) eWorld: JeffRay (jeffray@eworld.com) (805) 258-3754 CI$: 70661,2607 (70661.2607@compuserve.com) --------------------------- >From tycho@ele.uri.edu (Tycho Nightingale) Subject: Keyboard events from a background application Date: 6 May 1995 15:19:20 GMT Organization: URI Department of Electrical Engineering I am trying to write an application based screensaver, but I am having problems determining how long the computer has been idle. Finding out if the mouse has moved is pretty easy, just compare the mouse coordinates returned from OSEventAvail, but I am not having much luck determining if the keyboard has been idle. So far I have tried long sleep times in WaitNextEvent, and upon getting a null event checking the Event Queue for key down events, but unless a value of 0 is used for the sleep time this has not worked out. I have read the FAQs, and checked the usual archive sites for ideas but haven't found anything, any ideas would be appreciated. Thanks for any help, Tycho Nightingale tycho@vampyre.acc.uri.edu +++++++++++++++++++++++++++ >From mason@cis.umassd.edu (Mason Loring Bliss) Date: Sun, 7 May 1995 13:17:25 GMT Organization: University of Massachusetts Dartmouth In <3og41o$3us@egr.uri.edu> tycho@ele.uri.edu (Tycho Nightingale) writes: >I am trying to write an application based screensaver, but I am having >problems determining how long the computer has been idle. [...] >So far I have tried long sleep times in WaitNextEvent, and upon getting a >null event checking the Event Queue for key down events, but unless a >value of 0 is used for the sleep time this has not worked out. It doesn't work because you're missing a heck of a lot of keypresses. I'd use a different method... The way I do it is to patch SystemEvent(). This will not only let you record the time of every keystroke and mouseup/mousedown, but will also let you mask the keystroke or mousedown that wakes you up, which you want to do, right? Anyway, when you say "application-based," if you really mean "background application-based" then you can include the patch in the same file. If not, you'll probably have to do a seperate extension, as I don't think there's a way to make an application-hosted patch affect anything other than the application that applied it. Another possibility, if you're not worried about masking events: This is from the old-style headers, SysEqu.h: KeyTime = 0x186, /*[GLOBAL VAR] tickcount when KEYLAST was rec'd [long]*/ KeyRepTime = 0x18A,/*[GLOBAL VAR] tickcount when key was last repeated [long]*/ I can't find the Universal Headers equivalent, but it's got to be around somewhere. The last thing to worry about with application-based screensavers is this: what will you do when there's a modal dialog box on the screen? You won't be able to switch to the front. Don't get discouraged and you'll end up writing something that works. -- Mason Loring Bliss <> mason@acheron.middleboro.ma.us <> 1:109/370.6 Browse http://www.cis.umassd.edu/~mason for a copy of my PGP Public Key "...all which is forgotten need not necessarily be dead." - Lovecraft +++++++++++++++++++++++++++ >From Steve Sauder <nplains@passport.ca> Date: Sat, 13 May 1995 03:01:09 GMT Organization: North Plains Systems Inc. Tycho: It would seem to me that your problem stems from the fact that, when using a large sleep time in WaitNextEvent, your background app will only be woken up when an event is destined for it (which will never happen with user events like keyboard & mousedowns, since you're a faceless app...) To determine if any key has been pressed, you might want to look at using the GetKeys call, which will tell you if, at any given time, any keys on the Mac keyboard are down, using an array of Boolean values. This method circumvents the event queue altogether, and would therefore seem to be better suited to what you want to do. BTW, you'll still want to specify a fairly small sleep time in WNE, or you won't get any processing time in which to check the keys! Hope this helps! Regards, Steve - ------------------------------------------------------------------ Steve Sauder nplains@passport.ca North Plains Systems Inc. Macintosh Software for Electronic Publishing +++++++++++++++++++++++++++ >From chris-b@cs.auckland.ac.nz (chris-b) Date: Sun, 14 May 1995 15:09:46 -1200 Organization: HyperMedia Unit, Comp Sci, Auckland University In article <D8Hxpx.LC7@passport.ca>, Steve Sauder <nplains@passport.ca> wrote: >It would seem to me that your problem stems from the fact that, >when using a large sleep time in WaitNextEvent, your background >app will only be woken up when an event is destined for it (which >will never happen with user events like keyboard & mousedowns, >since you're a faceless app...) > >To determine if any key has been pressed, you might want to look >at using the GetKeys call, which will tell you if, at any given >time, any keys on the Mac keyboard are down, using an array of >Boolean values. This method circumvents the event queue altogether, >and would therefore seem to be better suited to what you want to >do. You could install a (now infamous) jGNEFilter. The jGNEFilter low-mem global contains the address of a function that gets called just before GNE/WNE returns to any application. This lets you check/modify/generate any event you desire. The jGNEFilter mechanism is unusual in that the filter you install is active across all applications (not just when you are in front). As usual, you need to save the address in jGNEFilter, install your own address, and in your filter, do your own stuff and then call through to the previous jGNEFilter (if not nil). Use archie to find the jGNEHelper sources. Chris B - --------------------------------------------------------------------- NewZealand:AucklandUniversity:ComputerScience:HyperMediaUnit:ChrisBurns Internet: chris-b@cs.auckland.ac.nz Phone: +64 9 373-7599 x6194 Fax: +64 9 373-7453 Async, therefore I am. - --------------------------------------------------------------------- --------------------------- >From dstone@alchemy.chem.utoronto.ca (David Stone) Subject: MIDI Books & other stuff Date: Wed, 17 May 1995 13:38:51 GMT Organization: University of Toronto Chemistry As promised, here is the info on the MIDI/Pascal book. MIDI Programming for the Macintosh Steve DeFuria and Joe Scacciaferro M&T Books 501 Galveston Drive, Redwood City CA94063 USA 1st Ed. 1988, available w/ or w/out disk 2nd Ed. 1993? I tried to order this but couldn't get it. It was listed in one of those "Books in Print" things but i have no idea if it's actually available. If anyone has seen it please let me know. There is also claimed to be a companion volume for Pascal which is not platform-specific by the same authors/publisher entitled "MIDI Programmer's Handbook". There is tons of useful information about MIDI in general via ftp from ftp.cs.ruu.nl//pub/MIDI/DOC and //pub/MIDI/PROGRAMS/MAC - use anonymous or ftp as login id and your email address as password. In particular get the docs with names midixxxxxxx or Mac-midi-xxxxx I've seen very little for MIDI C programming, and nothing for the Mac. The only books seem to be for PCs (Jim Conger's two from 1989, also M&T Books). >From some of the docs. I've downloaded, there also appears to be a MIDI mailing list somewhere, but there was no specific information. If anyone knows about this, maybe they could email me! I also downloaded a stuffit file called "midimerger" from somewhere (possibly ftp.cs.ruu.nl but it might have been somewhere else - I should log these things!). This contained a freeware MIDI driver for the Mac that is callable from Pascal or C using pascal conventions. It is very basic, includes time-stamping and has very few routines, so would be a good starting point - the Midi Manager is very intimidating, even with the SDK code examples. (Some of which didn't work when I got version 1.2). If anyone else has found good books/sources for MIDI on the Mac, I'd like to hear from you. I know that there are several others here working on MIDI projects. When I have spare time, I'm putting together a Metronome package that optionally uses the Sound Manager or MIDI to play the clicks. So far so good! Dave Stone --------------------------- >From english@primenet.com (Lawson English) Subject: New PowerPC Assembly Language Book Date: 9 May 1995 18:03:07 GMT Organization: Primenet Just got _Optimizing PowerPC Code: Programming the PowerPC Chip in Assembly Language_ by Gary Kacmarcik, Addison-Wesley, ISBN 0-201-40839-2. All in all, seems a decent book. Certainly more readable than the Motorola PowerPC 601 User's Handbook that I've been using, and makes MUCH more sense, as well. I've noted one or two minor typos (in the discussion on big- vs little-endian, the illustration (I think) mis-identifies big-endian bit-ordering as little-endian (p. 11) -but I'm dyslexic enough that *I* might be confused here :-/). Has interesting discussions on optimization from various perspectives like cache coherency, keeping the pipelines full, that sort of thing. Virtually all of the discussion is about the 601. The 603 is mentioned, but not the 604 or the 620. The book is NOT Mac-specific, nor IBM-specific, and in fact, doesn't address assembler details like TOC's, etc., at all. All in all, it is the very best book on PowerPC optimization that I have ever read, and I'd be willing to bet dollars to donuts that it is the best available. The fact that it is the *only* one available makes me pretty confident... Kidding aside, it is pretty good, and looks to be worth the money. Now if someone would just publish a book explaining how to actually *use* PPCAsm with MPW, or if MetroWerks really has added a function-level assembler, I'd be very happy indeed. -- - ----------------------------------------------------------------------------- Lawson English __ __ ____ ___ ___ ____ english@primenet.com /__)/__) / / / / /_ /\ / /_ / / / \ / / / / /__ / \/ /___ / - ----------------------------------------------------------------------------- +++++++++++++++++++++++++++ >From Bruce@hoult.actrix.gen.nz (Bruce Hoult) Date: Thu, 11 May 1995 14:30:58 +1200 (NZDT) Organization: (none) english@primenet.com (Lawson English) writes: > Kidding aside, it is pretty good, and looks to be worth the money. Now if > someone would just publish a book explaining how to actually *use* PPCAsm > with MPW, or if MetroWerks really has added a function-level assembler, > I'd be very happy indeed. What's the problem? I've always managed to do whatever I've wanted with PPCAsm, and either other MPW compilers or CodeWarrior, using the information in IM: PowerPC System Software and disassembling sample compiled functions. -- Bruce --------------------------- >From alain@cs.uchicago.edu (Alain Roy) Subject: Printing Styled TextEdit Date: Wed, 17 May 1995 00:28:33 GMT Organization: None So I have a program that does some manipulation of Styled TextEdit records. The user can type in a bunch of text and play with the font/size/style of any part of it. I'd like to print the text, with the styles. I'm not worried about being too fancy (no adjustable margins or headers on each page, or anything like that), I just want the text on the paper, but with the various fonts/sizes/styles. Do I have to do something gross like walking through the TextEdit data and printing it character by character, according to the style? That seems slow and painful. Or are there some tricks that I might be able to use get the text onto the paper? Although it's unlikely that users will have more than a page of data, I'd like to handle that correctly to. Does anyone have any suggestions? Thanks in advance. -alain +++++++++++++++++++++++++++ >From oster@netcom.com (David Phillip Oster) Date: Thu, 18 May 1995 00:52:37 GMT Organization: IOpener In article <alain-1605951928330001@hammer.uchicago.edu>, alain@cs.uchicago.edu (Alain Roy) wrote: > So I have a program that does some manipulation of Styled TextEdit > records. > I'd like to print the text, with the styles. What I do is temporarily set the GrafPtr field of the TERec, and thePort to the printer port, then call TEUpdate. This has worked for years in a commercial product. - ------- oster@netcom.com ---------- "A man hears what he wants to hear and misremembers the rest." -- Paul Simon, ("The Boxer") +++++++++++++++++++++++++++ >From jens_alfke@powertalk.apple.com (Jens Alfke) Date: Thu, 18 May 1995 17:29:19 GMT Organization: Apple Computer, Inc. In article <alain-1605951928330001@hammer.uchicago.edu>, alain@cs.uchicago.edu (Alain Roy) wrote: > I'd like to print the text, with the styles. I'm not worried about being > too fancy (no adjustable margins or headers on each page, or anything like > that), I just want the text on the paper, but with the various > fonts/sizes/styles. > > Do I have to do something gross like walking through the TextEdit data and > printing it character by character, according to the style? That seems > slow and painful. Just print it the way you print anything else -- make the print mgr incantations to open a printing grafport, then make a TE record in it and call TEUpdate. If you're worried about memory usage you can even take your existing TE record and munge it to point into the new port with the new bounding box. Doing nice page breaks so the lines aren't broken across page boundaries takes a bit of work. You have to find the nearest line break above the page break and clip the viewRect to there, then move the text up by that distance when you go to print the next page. Jens Alfke_________OpenDoc Geometer_________jens_alfke@powertalk.apple.com OpenDoc info: FTP to CILabs.org LLAMA: NO FEAR OF SPIKES +++++++++++++++++++++++++++ >From jens_alfke@powertalk.apple.com (Jens Alfke) Date: Thu, 18 May 1995 17:30:53 GMT Organization: Apple Computer, Inc. Addendum to my previous posting: Don't forget to call FractEnable(true) to turn on fractional widths before laying out the text, or the character spacing and margins may be screwed up. Be aware that this will change the layout, so if you're using the same TE record as on screen you should call TECalText afterwards so TE can recompute the line breaks. If you don't use fractional widths on screen, call FractEnable(false) when you're done printing. Jens Alfke_________OpenDoc Geometer_________jens_alfke@powertalk.apple.com OpenDoc info: FTP to CILabs.org LLAMA: NO FEAR OF SPIKES --------------------------- >From chaoyang@phakt.usc.edu (Mark Yang) Subject: QuickDraw 3D Info Date: 5 May 1995 08:45:43 GMT Organization: Z-Perception Graphics Hi! Does anybody in the net know where I can get some info on QuickDraw 3D API and information? I am so desperate! Mark Yang +++++++++++++++++++++++++++ >From jl@ct.ix.de (Jvrn Loviscach) Date: Mon, 8 May 1995 12:46:20 GMT Organization: Redaktion c't In article <chaoyang-0505950150090001@comserv-e-3.usc.edu>, chaoyang@phakt.usc.edu (Mark Yang) says: > Does anybody in the net know where I can get some info on QuickDraw 3D >API and information? I am so desperate! Me too!!! But, nontheless, I know the eMail address of Apple'e QuickDraw 3D evangelist:S.HOPWOOD@applelink.apple.com - -Joern Loviscach +++++++++++++++++++++++++++ >From rodden@cse.ucsc.edu (James Rodden) Date: Tue, 09 May 1995 01:31:58 -0700 Organization: DD/MF & Associates In article <D89FH8.Ht2@ix.de>, jl@ct.ix.de (Jvrn Loviscach) wrote: >In article <chaoyang-0505950150090001@comserv-e-3.usc.edu>, chaoyang@phakt.usc.edu (Mark Yang) says: > >> Does anybody in the net know where I can get some info on QuickDraw 3D >>API and information? I am so desperate! > >Me too!!! But, nontheless, I know the eMail address of >Apple'e QuickDraw 3D evangelist:S.HOPWOOD@applelink.apple.com If you really want QD3D info avaiable on the net (or any other key technology), you should bug the appropriate evangelism group and Apple Developer University to publish an overview course on the web. Explain to them how benificial it would be to the mac community at large and would lure more developers to the Mac platform, etc. There are currently three courses online now at http://www.info.apple.com/dev/du/online.html and one more waiting to be put on the server. I think these courses are a very good thing, if you agree let DU know!!! Unfortunately, the project to convert courses to the web has been stalled. Disclaimer: this is a "slightly" self-motivated plug. Although I do stand to benefit from this project (I'm the one whose been doing the html conversions), I feel strongly that this is an important project. Jim -- J.Rodden, DD/MF & Associates Simlab Development Team, Product Architect This message contains content that may be offensive to some readers. Some sexual content is not supposed to be viewed by those under 18 according to U.S. laws. You will unfortunately see this type of annoying notice throughout the net. Right now, that's only because we're trying to prove a point. If the amended version of US Senator Exon's "Decency Act", S.314, now tacked onto the telecomm reform bill, passes we'll all be required to put these notices everywhere. Please contact your Congressmen to protest the bill. Please, put warnings like this in your own electronic communications, to spread the word about what the future of the net could be like if we don't act. +++++++++++++++++++++++++++ >From jeg@apple.com (Julian E Gomez) Date: Wed, 17 May 1995 18:17:19 -0800 Organization: Apple Computer, Inc. > In article <chaoyang-0505950150090001@comserv-e-3.usc.edu>, chaoyang@phakt.usc.edu (Mark Yang) says: > > > Does anybody in the net know where I can get some info on QuickDraw 3D > >API and information? I am so desperate! We have started the process of making information available online. Check out http://www.info.apple.com/qd3d/QD3D.HTML -- Windows 96 == Macintosh 85 Dr. Julian "a tribble took it" Gomez QuickDraw 3D Development Team Apple Computer, Inc. 408/862-1289 or 996-1010 jeg@apple.com julian.g@applelink.apple.com --------------------------- >From hc7@aixterm1.urz.uni-heidelberg.de (Roland Werner) Subject: QuickTake API? Date: 4 May 1995 05:28:14 GMT Organization: University of Heidelberg, Germany Do there exists a programmer interface for the Quicktake100 digital camera? I want to make photographs periodically and paste them in a WWW homepage. Thanks! Dipl.-Inform. Med. Roland Werner Roland_Werner@KRZMAIL.KRZ.UNI-HEIDELBERG.DE +++++++++++++++++++++++++++ >From jonpugh@netcom.com (Jon Pugh) Date: Sat, 13 May 1995 20:42:36 GMT Organization: Not Organized In article <3o9ole$goo@sun0.urz.uni-heidelberg.de>, hc7@aixterm1.urz.uni-heidelberg.de (Roland Werner) wrote: > Do there exists a programmer interface for the Quicktake100 > digital camera? I want to make photographs periodically and > paste them in a WWW homepage. There is an API which is going to be published via APDA and the MacOS SDK. It's basically some glue and driver calls. A simple solution is to use AppleScript. There is a scripting addition which provides access to all the camera's functionality. If you didn't get this scripting addition when you bought the camera, then you will still need the SDK since it ships with that. It also ships with PhotoFlash 2.0 from Apple (about $99 from US mail order distributers) so that is another option. The new QuickTake 150 includes both PhotoFlash and the scripting addition. Jon What are YOU doing to oppose the Microsoft juggernaut? ftp://ftp.netcom.com/pub/jo/jonpugh/homepage.html --------------------------- >From S.W.Lay@damtp.cam.ac.uk (Steve Lay) Subject: WakeUpProcess at Interrupt Time Date: Wed, 03 May 1995 17:35:50 +0100 Organization: DAMTP, Cambridge University In my faithful IM6 'WakeUpProcess' is listed as being callable at interrupt time. At first I thought this might be useful but.... My problem is that I have a program which starts an async IO call going and would like to go to sleep until the call completes. (For the sake of argument lets say its a PPC call and I'm waiting for a connection.) I thought that by carefully storing my psn in a place which I could find again at interrupt time I'd be able to wake-up my sleeping process and do the next (non-async) stage in my program. Unfortunately, I think I'm getting bitten by a rapid completion. That is my completion routine gets called before I'm suspended so (I guess) WakeUpProcess does nothing. I then unwittingly specify a nice long time to go to sleep for, making my response to the IO v e r y slow. The obvious answer is not to go to sleep for so long but in rapid-fire IO situations anything other than 0 would be a visible performance hit. On the other hand the idea of sitting there for hours specifying a sleep value of 0 'just in case' seems like a real waste of processor time. At the moment the only strategy I can think of is an 'adaptive sleep size' method which tentatively increases the sleep time up to a tolerable maximum. Anyone got a better solution? Surely all those clever MacTCP boffins must have sorted this kind of thing out? -- Steve Lay S.W.Lay@damtp.cam.ac.uk http://www.amtp.cam.ac.uk/icrd/ +++++++++++++++++++++++++++ >From hueras@tiac.net (Jon Hueras) Date: Wed, 03 May 1995 22:52:16 -0500 Organization: The Internet Access Company In article <S.W.Lay-0305951735500001@corylus.amtp.cam.ac.uk>, S.W.Lay@damtp.cam.ac.uk (Steve Lay) wrote: > In my faithful IM6 'WakeUpProcess' is listed as being callable at > interrupt time. At first I thought this might be useful but.... > > My problem is that I have a program which starts an async IO call going > and would like to go to sleep until the call completes. (For the sake of > argument lets say its a PPC call and I'm waiting for a connection.) I > thought that by carefully storing my psn in a place which I could find > again at interrupt time I'd be able to wake-up my sleeping process and do > the next (non-async) stage in my program. > > Unfortunately, I think I'm getting bitten by a rapid completion. That is > my completion routine gets called before I'm suspended so (I guess) > WakeUpProcess does nothing. I then unwittingly specify a nice long time > to go to sleep for, making my response to the IO v e r y slow. Presumably, when your I/O call completes you record the completion in some fashion, either by setting a flag or inserting something into a queue or even just relying on ioResult. However you do it, you need some means of independently testing whether it's time to wake up your process again and you need to ensure that such a test can be performed quickly. Having done this, set up a Time Manager task that periodically performs this test and calls WakeUpProcess as needed. Since the test involves almost no overhead, you can set the task interval's fuse almost as short as you like (as often as a tick even, but I wouldn't make it any shorter than a millisecond or you *will* impact the overall system). You need to do this because there's no way to *guarantee* that you'll sleep before the call completes. However, it doesn't hurt to keep the "window of opportunity" as narrow as possible by checking for completion just before going to sleep. Hope this helps. Jon +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D9Oliveiro) Date: Fri, 05 May 1995 18:28:08 +1200 Organization: University of Waikato In article <S.W.Lay-0305951735500001@corylus.amtp.cam.ac.uk>, S.W.Lay@damtp.cam.ac.uk (Steve Lay) wrote: >In my faithful IM6 'WakeUpProcess' is listed as being callable at >interrupt time. At first I thought this might be useful but.... > >My problem is that I have a program which starts an async IO call going >and would like to go to sleep until the call completes. Thot: I recall a "feature" of some past version of the Process Manager, whereby it would not switch out a process that had async I/O pending. Anybody know if this still applies? >Unfortunately, I think I'm getting bitten by a rapid completion. That is >my completion routine gets called before I'm suspended so (I guess) >WakeUpProcess does nothing. I then unwittingly specify a nice long time >to go to sleep for, making my response to the IO v e r y slow. This is what's known as a "race condition". Concurrent-programming veterans get bitten by it all the time. :-) Ideally, here's the sequence of events you want to have happen: * start the async I/O operation. * enter critical section (in this case, it means blocking the completion routine from running). * check if operation has completed. If it has, then leave critical section, and skip next step. * If operation hasn't completed, then put process to sleep, and leave critical section, in a single indivisible operation. Interestingly enough, the Thread Manager offers a call which does something resembling the last step, but the Process Manager has no equivalent functionality. Alternatively, it would be nice if the Process Manager maintained a one-shot "wake pending" flag that would be set if you called WakeUpProcess on a process that wasn't asleep; then the sleep time on the next WaitNextEvent call would be forced to zero, so it returned immediately (and the flag was cleared). >The obvious answer is not to go to sleep for so long but in rapid-fire IO >situations anything other than 0 would be a visible performance hit. On >the other hand the idea of sitting there for hours specifying a sleep >value of 0 'just in case' seems like a real waste of processor time. The issue is not burning CPU time that would otherwise go idle, but whether you would hurt the responsiveness of other applications. If all you're doing is checking a simple flag and then calling WaitNextEvent again, it seems to me the responsiveness hit wouldn't be too bad (unless you're on a PowerMac, where you could be incurring lots of mixed-mode transitions). > At >the moment the only strategy I can think of is an 'adaptive sleep size' >method which tentatively increases the sleep time up to a tolerable >maximum. I can't think of any way to make this foolproof. The race condition could still bite you. Beginnings of an idea: how about the I/O completion routine starting something like a periodic vertical blanking or Time Manager task, that kept repeatedly calling WakeUpProcess until it was cancelled by the mainline? +++++++++++++++++++++++++++ >From jumplong@aol.com (Jump Long) Date: 7 May 1995 13:47:20 -0400 Organization: America Online, Inc. (1-800-827-6364) >In my faithful IM6 'WakeUpProcess' is listed as being callable at >interrupt time. At first I thought this might be useful but.... > >My problem is that I have a program which starts an async IO call going >and would like to go to sleep until the call completes. (For the sake >of argument lets say its a PPC call and I'm waiting for a connection.) >I thought that by carefully storing my psn in a place which I could find >again at interrupt time I'd be able to wake-up my sleeping process and >do the next (non-async) stage in my program. > >Unfortunately, I think I'm getting bitten by a rapid completion. That >is my completion routine gets called before I'm suspended so (I guess) >WakeUpProcess does nothing. I then unwittingly specify a nice long time >to go to sleep for, making my response to the IO v e r y slow. That's a bug in the Process Manager that has been fixed (I think it was fixed with either System 7.1.2 or System Update 3.0). The bug was: If the process being awakened by WakeUpProcess was the current process, then the WakeUpProcess call was ignored. Here's the work-around we (Developer Support) recommend: 1) The code that calls WakeUpProcess at interrupt time should set a global variable used for the process' WaitNextEvent sleep time to zero. That way, if the race condition is encountered, it has minimal effect. The processes code that processes the data your interrupt time code is waking it up for can set the sleep variable back to the normal value after it has processed the data. 2) Just before calling WakeUpProcess, the process can check the global variable used for sleep time to see it it's zero and if it is, call the code that does the processing. This reduces the window of time that the race condition can occur in. 3) If the application is expecting interrupt time code to wake it up (for example, it has a connection open), it should use a "medium-sized" sleep value for WaitNextEvent rather than a large sleep value. For example, if my program had an ADSP connection open and the data recieved by ADSP had to be processed from my program's event loop, then I might use a sleep time of 5 seconds (300 ticks) so that even if I hit the small race condition window, the Process Manager will still wake me up after about 5 seconds. - Jim Luther --------------------------- End of C.S.M.P. Digest **********************